using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Markup;
using WPFPractice.Models;
using WPFPractice.Utils;
using WPFPractice.ViewModels;

namespace WPFPractice.Windows
{
	/// <summary>
	/// 动态列表格演示窗口
	/// [WPF 中 DataGrid 如何动态生成列及自定义表头结构](https://zhuanlan.zhihu.com/p/552909950)
	/// </summary>
	public partial class WinDataGridAutoCol : Window
	{
		public WinDataGridAutoCol()
		{
			InitializeComponent();
			DataContext = new DataGridAutoColViewModel();
			AutoGenerateDataGridColumns();
		}

		/// <summary>
		/// 动态生成DataGrid的列
		/// </summary>
		private void AutoGenerateDataGridColumns()
		{
			var dpDescriptor = DependencyPropertyDescriptor.FromProperty(DataGrid.ItemsSourceProperty, typeof(DataGrid));
			dpDescriptor.AddValueChanged(dataGrid, (s, e) =>
			{
				dataGrid.Columns.Clear();

				if(dataGrid.ItemsSource is List<List<object>> dataSource && dataSource?.Count > 0)
				{
					var columnHeaderStyle = this.FindResource("FactorColumnHeaderStyle") as Style;
					var firstRow = dataSource.First();
					for(int i = 0; i < firstRow.Count; i++)
					{
						if(firstRow[i] is Factor factor)
						{
							// 表头绑定的数据源
							var factorHeaderSource = new FactorColumnHeaderModel()
							{
								HasFlag = true,
								Header = factor.Name,
								SubHeaders = new List<string>() { "最小值", "均值", "最大值" }
							};

							// 列中元素绑定的数据源
							var bindingList = new List<string>();
							bindingList.Add($"[{i}].Min");
							bindingList.Add($"[{i}].Avg");
							bindingList.Add($"[{i}].Max");
							bindingList.Add($"[{i}].Flag");
							var factorCellTemplateStr = GetCellTemplateXaml(bindingList, factorHeaderSource.HasFlag);
							var templateColumn = new DataGridTemplateColumn()
							{
								Header = factorHeaderSource,
								HeaderStyle = columnHeaderStyle,
								CellTemplate = (DataTemplate)XamlReader.Parse(factorCellTemplateStr)
							};
							this.dataGrid.Columns.Add(templateColumn);
						}
						else
						{
							this.dataGrid.Columns.Add(new DataGridTextColumn()
							{
								Header = "时间",
								IsReadOnly = true,
								Binding = new Binding("[" + i.ToString() + "]")
								{
									StringFormat = "yyyy/MM/dd HH:mm:ss"
								},
								ElementStyle = (Style)this.FindResource("DataGridTextColumnStyle")
							});
						}
					}
				}
			});
		}

		/// <summary>
		/// 生成DataTemlate的代码片段
		/// </summary>
		/// <param name="cellBindingList">每个元素对应的数据绑定字符串集合</param>
		/// <param name="hasFlag">是否包含独立的标记列（对应表头）</param>
		/// <returns></returns>
		public static string GetCellTemplateXaml(List<string> cellBindingList, bool hasFlag)
		{
			var templateStr = "<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">";
			templateStr += "<Grid><Grid.ColumnDefinitions><ColumnDefinition Width=\"*\" /><ColumnDefinition Width=\"Auto\" /></Grid.ColumnDefinitions>";
			templateStr += $"<UniformGrid Columns=\"{(hasFlag ? cellBindingList.Count - 1 : cellBindingList.Count)}\">";
			cellBindingList.ForEach(a =>
			{
				if(!hasFlag || a != cellBindingList.Last())
				{
					templateStr += "<TextBlock Margin=\"10 0 10 0\" Text=\"{Binding " + a + "}\" VerticalAlignment=\"Center\" HorizontalAlignment=\"Center\" />";
				}
			});
			templateStr += "</UniformGrid>";
			if(hasFlag)
			{
				templateStr += "<TextBlock Grid.Column=\"1\" Text=\"{Binding " + cellBindingList.Last() + "}\" Width=\"50\" TextAlignment=\"Center\" VerticalAlignment=\"Center\" HorizontalAlignment=\"Center\" />";
			}
			templateStr += "</Grid></DataTemplate>";
			return templateStr;
		}
	}
}

namespace WPFPractice.ViewModels
{
	public class DataGridAutoColViewModel : MyViewModelBase
	{
		#region 绑定

		public List<List<object>> DataSource { get; set; }

		#endregion

		#region 方法

		/// <inheritdoc />
		protected override void InitDataAfterConstruction()
		{
			var dataSource = new List<List<object>>();
			for(int i = 0; i < 5; i++)
			{
				var row = new List<object>
				{
					DateTime.Now.AddDays(i),
					new Factor { Name = "CO2", Min = "12.34" + i, Avg = "13.45" + i, Max = "14.56" + i, Flag = "N"},
					new Factor { Name = "NO2", Min = "23.14" + i, Avg = "25.25" + i, Max = "27.36" + i, Flag = "N" },
					new Factor { Name = "SO2", Min = "34.45" + i, Avg = "35.56" + i, Max = "36.67" + i, Flag = "N" }
				};

				dataSource.Add(row);
			}

			DataSource = dataSource;
		}

		#endregion
	}
}

namespace WPFPractice.Models
{
	public class Factor
	{
		public string Name { get; set; }
		public string Min { get; set; }
		public string Avg { get; set; }
		public string Max { get; set; }
		public string Flag { get; set; }
	}

	public class FactorColumnHeaderModel
	{
		public string Header { get; set; }
		public List<string> SubHeaders { get; set; }

		/// <summary>
		/// 由于标记列可能不需要显示，所以单独用布尔类型绑定
		/// </summary>
		public bool HasFlag { get; set; } = true;
	}

}
